import React, { useCallback, useEffect, useMemo, useState } from "react";
import {
    Divider,
    Empty,
    Spin,
} from 'antd'
import './style.less'
import { DataSourceResultField } from "./DataSourceResultField";
import { ResultHeader } from "@/components/DataFlow/common/ResultHeader";
import { useCurrentNode } from "@/hooks/useCurrentNode";
import { useNodesData, useReactFlow } from "@xyflow/react";
import { RESULT_SHOW_MODE_DICT } from "@/constant/icons";
import { DataSourceResultData } from "./DataSourceResultData";
import { getFlowColumns } from "@/api";
import { useModelStore } from "@/store/MetaModel";
import { cloneDeep, debounce, isEqual } from "lodash-es";
import {motion} from 'motion/react'
import { normalizeFieldType } from "@/utils/dataflow";

export const DataSourceResult = () => {
    const currentNode = useCurrentNode()
    const nodeData = useNodesData(currentNode?.id)
    const { updateNodeData } = useReactFlow()
    const [searchValue, setSearchValue] = useState('')
    const [showMode, setShowMode] = useState(RESULT_SHOW_MODE_DICT.field)
    const [loading, setLoading] = useState(false)
    const { idSpace, vluTabSource } = useModelStore()

    const { allColumns: dataSource, columns, tableName } = nodeData?.data || {};

    const fetchColumns = useCallback(debounce(() => {
        if (!tableName) return;
        setLoading(true);
        getFlowColumns({
            namTable: tableName,
            idSpace,
            vluTabSource,
        }).then(res => {
            const newData = res?.data?.map(d => {
                return {
                    columnName: d.namColumn,
                    columnType: normalizeFieldType(d.vluColType),
                    columnComment: d.vluColComments,
                    columnId: d.idColumn
                }
            }) ?? []
            updateNodeData(currentNode?.id, {
                allColumns: newData,
                columns: cloneDeep(newData)
            });
        }).finally(() => setLoading(false));

    }, 300), [tableName, dataSource, columns]);

    useEffect(() => {
        if (tableName) {
            fetchColumns();
        }
    }, [tableName]);

    const searchResult = useMemo(() => {
        if (!searchValue) return dataSource
        return dataSource?.filter(s => s.columnName?.indexOf(searchValue) > -1)
    }, [dataSource, searchValue])

    const handleSelectionChange = (items) => {
        // 将当前选中的项转换为Set以便快速查找
        const selectedNames = new Set(items.map(item => item.columnName || item));

        let finalColumns;

        if (searchValue) {
            // 当有搜索值时，我们需要:
            // 1. 保留不在searchResult中的现有列
            // 2. 更新在searchResult中的列（根据当前选择状态）

            // 获取searchResult中的所有列名
            const searchResultNames = new Set(
                searchResult?.map(col => col.columnName) || []
            );

            // 分为两部分处理：
            // 1. 保留不在searchResult中的现有列
            const columnsOutsideSearch = (columns || []).filter(
                col => !searchResultNames.has(col.columnName)
            );

            // 2. 处理searchResult中的列 - 只保留被选中的
            const columnsFromSearch = (searchResult || []).filter(
                col => selectedNames.has(col.columnName)
            );

            // 合并两部分
            finalColumns = [...columnsOutsideSearch, ...columnsFromSearch];
        } else {
            // 没有搜索值时，直接用所有选中的列
            finalColumns = dataSource?.filter(d => selectedNames.has(d.columnName)) || [];
        }

        // 更新节点数据
        updateNodeData(currentNode?.id, { columns: finalColumns });
    };
    const selectedRowKeys = useMemo(() => {
        return nodeData?.data?.columns?.map(c => c.columnName)
    }, [nodeData])

    const renderContent = () => {
        if (showMode === RESULT_SHOW_MODE_DICT.data) {
            return <motion.div
            key="data"
            initial={{ opacity: 0, x: 10 }}
            animate={{ opacity: 1, x: 0 }}
            exit={{ opacity: 0, x: -10 }}
            transition={{ duration: 0.2 }}
        >
            <DataSourceResultData />
        </motion.div >
        } else if (showMode === RESULT_SHOW_MODE_DICT.field) {
            return <DataSourceResultField datasource={searchResult}
                onSelectionChange={handleSelectionChange} selectedKeys={selectedRowKeys} />
        } else {
            return <Empty />
        }
    }

    return (
        <div className="datasource-container">
            <ResultHeader info="数据输入"
                total={dataSource?.length ?? 0}
                select={columns?.length ?? 0}
                mode={showMode}
                onChange={setShowMode}
                onSearch={setSearchValue}
            />
            <Divider style={{ margin: '8px 0' }} />

            <div style={{ height: '100%', width: 'calc(100% - 15px)' }}>
                <Spin spinning={loading}>
                    {
                        renderContent()
                    }
                </Spin>
            </div>
        </div>
    );
};